package org.btik.context.handler;

import org.btik.context.AppContext;
import org.btik.context.ContextHolder;
import org.btik.context.event.SystemShutdownHook;
import org.btik.context.event.SystemStartHook;
import org.btik.context.thread.SystemControlAble;

import java.util.Comparator;
import java.util.List;

/**
 * 进程实例生命周期控制器
 */
public class LifecycleController implements SystemShutdownHook {
    /**
     * 当context返回的SystemStartHook 实例顺序有依赖时，且无法按顺序将对应实例载入context
     * 可以通过实例类返回的index进行排序，此处为是否开启该排序的开关
     */
    private boolean sortByIndex;

    public void setSortByIndex(boolean sortByIndex) {
        this.sortByIndex = sortByIndex;
    }

    private List<SystemControlAble> systemControlAbles;

    public void doAppStart(AppContext context) {
        holdContext(context);
        onSystemStart(context);

        registerShutDownHook(context);


        launcherControlAble(context);

    }

    /**
     * 拉起系统什么周期相同的线程
     */
    private void launcherControlAble(AppContext context) {
        systemControlAbles = context.getBeans(SystemControlAble.class);
        for (SystemControlAble systemControlAble : systemControlAbles) {
            systemControlAble.start();
        }
    }

    /**
     * 注册停机事件
     */
    private void registerShutDownHook(AppContext context) {
        ShutdownHandler shutdownHandler = context.getBean(ShutdownHandler.class);
        List<SystemShutdownHook> shutDownHooks = context.getBeans(SystemShutdownHook.class);
        for (SystemShutdownHook shutDownHook : shutDownHooks) {
            shutdownHandler.register(shutDownHook);
        }
    }

    /**
     * 拉起启动事件
     */
    private void onSystemStart(AppContext context) {

        List<SystemStartHook> systemStartHooks = context.getBeans(SystemStartHook.class);
        if (sortByIndex) {
            systemStartHooks.sort(Comparator.comparingInt(SystemStartHook::index));
        }

        // 此处需要顺序遍历 不能使用并行遍历
        for (SystemStartHook systemStartHook : systemStartHooks) {
            systemStartHook.onSystemStart(context);
        }
    }

    /**
     * 持有context
     */
    private void holdContext(AppContext context) {
        List<ContextHolder> contextHolders = context.getBeans(ContextHolder.class);
        for (ContextHolder contextHolder : contextHolders) {
            contextHolder.hold(context);
        }
    }

    public void onShutDown(String msg) {
        if (null == systemControlAbles) {
            return;
        }
        for (SystemControlAble systemControlAble : systemControlAbles) {
            systemControlAble.shutdown(msg);
        }
    }


    @Override
    public void beforeShutdown(AppContext appContext) {
        onShutDown("shutdown ");
    }
}
